# 元素定位及等待封装类
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class LocalUtil:

    def __init__(self, driver, timeout=20):
        self.driver = driver
        self.timeout = timeout  # 默认等待10秒

    def wait_for_element(self, by, value):
        """
        查找单个元素（带显示等待）
        :param by: 定位器，格式为（定位方法，定位表达式）
        :param value: 超市时间（秒），不传则使用默认等待时间
        :return: WebElement对象
        """
        try:
            element = WebDriverWait(self.driver, self.timeout).until(
                EC.presence_of_element_located((by, value))
            )
            return element
        except TimeoutException:
            print(f"元素 {value} 没有在 {self.timeout} 内加载完成")
            return None

    def wait_for_elements(self, by, value):
        """
        查找多个元素（带显示等待）
        :param by: 定位器，格式为（定位方法，定位表达式）
        :param value: 超市时间（秒），不传则使用默认等待时间
        :return: WebElement列表
        """
        try:
            elements = WebDriverWait(self.driver, self.timeout).until(
                EC.presence_of_all_elements_located((by, value))
            )
            return elements
        except TimeoutException:
            print(f"元素 {value} 没有在 {self.timeout} 秒内加载完成")
            return []

    def wait_for_element_present(self, by, value):
        """
        判断元素是否存在
        :param by:定位方法
        :param value: 定位文本
        :return: 布尔值
        """
        try:
            element = WebDriverWait(self.driver, self.timeout).until(
                EC.visibility_of_element_located((by, value))
            )
            return element
        except TimeoutException:
            print(f"元素 {value} 没有在 {self.timeout} 秒内可见")
            return None

    def is_element_visible(self, locator, timeout=None):
        """
        判断元素是否可见
        :param locator:定位器
        :param timeout: 超时时间
        :return:布尔
        """
        try:
            if timeout is not None:
                wait = WebDriverWait(self.driver, timeout)
            else:
                wait = self.timeout
            wait.until(EC.visibility_of_element_located(locator))
            return True
        except TimeoutException:
            return False

    def wait_for_element_clickable(self, by, value):
        """
        等待元素可点击
        :param by: 定位方法
        :param value: 定位文本
        :return: WebElement对象
        """
        try:
            element = WebDriverWait(self.driver, self.timeout).until(
                EC.element_to_be_clickable((by, value))
            )
            return element
        except TimeoutException:
            print(f"元素{value} 没有在 {self.timeout}秒内可点击")
            return None

    def wait_for_text_present(self, locator, text, timeout=None):
        """
        等待元素包含特定文本
        :param locator: 定位器
        :param text: 等待出现的文本
        :param timeout: 超时时间
        :return: 布尔值
        """
        try:
            if timeout is not None:
                wait = WebDriverWait(self.driver, timeout)
            else:
                wait = self.wait
            wait.until(EC.text_to_be_present_in_element(locator, text))
            return True
        except TimeoutException:
            return False

    def wait_for_page_loaded(self, timeout=30):
        """
        等待页面完全加载
        :param timeout: 超时时间
        """
        try:
            WebDriverWait(self.driver, timeout).until(
                lambda driver: driver.execute_script("return document.readyState") == "complete"
            )
        except TimeoutException:
            raise TimeoutException(f"页面在{timeout}秒内未完全加载")
